package org.nanhill.commons.xml;

import static org.nanhill.commons.lang.StringConstants.GT;
import static org.nanhill.commons.lang.StringConstants.LT;
import static org.nanhill.commons.lang.StringConstants.QUOT;
import static org.nanhill.commons.xml.XmlConstants.AMP;
import static org.nanhill.commons.xml.XmlConstants.AMP_ESCAPE_ARRAY;
import static org.nanhill.commons.xml.XmlConstants.AMP_ESCAPE_LEN;
import static org.nanhill.commons.xml.XmlConstants.APOS;
import static org.nanhill.commons.xml.XmlConstants.APOS_ESCAPE_ARRAY;
import static org.nanhill.commons.xml.XmlConstants.APOS_ESCAPE_LEN;
import static org.nanhill.commons.xml.XmlConstants.GT_ESCAPE_ARRAY;
import static org.nanhill.commons.xml.XmlConstants.GT_ESCAPE_LEN;
import static org.nanhill.commons.xml.XmlConstants.LT_ESCAPE_ARRAY;
import static org.nanhill.commons.xml.XmlConstants.LT_ESCAPE_LEN;
import static org.nanhill.commons.xml.XmlConstants.QUOT_ESCAPE_ARRAY;
import static org.nanhill.commons.xml.XmlConstants.QUOT_ESCAPE_LEN;

import java.io.IOException;
import java.io.Writer;

/**
 * Xml escape writer.
 * 
 * @author alin [xalinx at gmail dot com]
 * @date 2006-10-11
 */
public class XmlEscapeWriter extends Writer {
	/**
	 * Wrapped writer.
	 */
	private final Writer out;

	/**
	 * @param out
	 */
	public XmlEscapeWriter(Writer out) {
		this.out = out;
	}

	public void write(int c) throws IOException {
		switch (c) {
		case LT:
			out.write(LT_ESCAPE_ARRAY, 0, LT_ESCAPE_LEN);
			break;
		case GT:
			out.write(GT_ESCAPE_ARRAY, 0, GT_ESCAPE_LEN);
			break;
		case AMP:
			out.write(AMP_ESCAPE_ARRAY, 0, AMP_ESCAPE_LEN);
			break;
		case QUOT:
			out.write(QUOT_ESCAPE_ARRAY, 0, QUOT_ESCAPE_LEN);
			break;
		case APOS:
			out.write(APOS_ESCAPE_ARRAY, 0, APOS_ESCAPE_LEN);
			break;
		default:
			out.write(c);
		}
	}

	public void write(char cbuf[], int off, int len) throws IOException {
		int lastoff = off;
		int lastpos = off + len;
		for (int i = off; i < lastpos; i++) {
			switch (cbuf[i]) {
			case LT:
				out.write(cbuf, lastoff, i - lastoff);
				out.write(LT_ESCAPE_ARRAY, 0, LT_ESCAPE_LEN);
				lastoff = i + 1;
				break;
			case GT:
				out.write(cbuf, lastoff, i - lastoff);
				out.write(GT_ESCAPE_ARRAY, 0, GT_ESCAPE_LEN);
				lastoff = i + 1;
				break;
			case AMP:
				out.write(cbuf, lastoff, i - lastoff);
				out.write(AMP_ESCAPE_ARRAY, 0, AMP_ESCAPE_LEN);
				lastoff = i + 1;
				break;
			case QUOT:
				out.write(cbuf, lastoff, i - lastoff);
				out.write(QUOT_ESCAPE_ARRAY, 0, QUOT_ESCAPE_LEN);
				lastoff = i + 1;
				break;
			case APOS:
				out.write(cbuf, lastoff, i - lastoff);
				out.write(APOS_ESCAPE_ARRAY, 0, APOS_ESCAPE_LEN);
				lastoff = i + 1;
				break;
			}
		}
		int remaining = lastpos - lastoff;
		if (remaining > 0) {
			out.write(cbuf, lastoff, remaining);
		}
	}

	public void flush() throws IOException {
		out.flush();
	}

	public void close() throws IOException {
		out.close();
	}
}